
import * as Sequelize from 'sequelize'
import Relation from '../lib/relation';
import * as path from 'path'
import { forOwn } from 'lodash'
import { DbOp, ctx } from '../utils/iface';
import * as send from 'koa-send'
import ErrorType from '../utils/errors';
import * as process from 'process'
var connection = null;
export default class Config {
    public _ctx: any;
    constructor(ctx?: ctx) {
        if (ctx) {
            this.controller(ctx)
            this._ctx = ctx;
        }
    }
    get AppDebug() {
        return process.env.NODE_ENV=="production";
    }
    get AppPath() {
        return './dist'
    }
    sendFile: boolean = false;
    get session(): SessionOptions {
        return {
            key: 'castlekoa', /** (string) cookie key (default is koa:sess) */
            /** (number || 'session') maxAge in ms (default is 1 days) */
            /** 'session' will result in a cookie that expires when session/browser is closed */
            /** Warning: If a session cookie is stolen, this cookie will never expire */
            path: '.sess',
            maxAge: 86400000,
            overwrite: true, /** (boolean) can overwrite or not (default true) */
            httpOnly: true, /** (boolean) httpOnly or not (default true) */
            signed: true, /** (boolean) signed or not (default true) */
            rolling: false, /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */
            renew: false, /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/
        }
    }
    get dbConfig(): any {
        return {
            database: 'test',
            username: 'root',
            password: '123456',
            options: {
                host: 'localhost',
                port: 3306,
                dialect: 'mysql',
                operatorsAliases: DbOp,
                timezone: '+8:00',
                pool: { max: 5, min: 1, acquire: 3000, idle: 1000 },
                logging: (content) => {
                    //TODO LOG 写入到ctx的log中，在最终的时候写入log文件
                    console.log(content)
                }
            },
        }
    }
    get dbPrefix() {
        return '';
    }
    get db(): Sequelize.Sequelize {
        if (!connection) {
            connection = new Sequelize(this.dbConfig.database, this.dbConfig.username, this.dbConfig.password, Object.assign(this.dbConfig.options, { operatorsAliases: DbOp }));
        }
        return connection;
    }
    protected _trans;
    protected _transTimes = 0;
    async startTrans() {
        this._transTimes++;
        if (this._trans) {
            return this._trans;
        }
        this._trans = await this.db.transaction()
        return this._trans;
    }
    async commit() {
        this._transTimes--;
        if (this._trans && this._transTimes == 0) {
            await this._trans.commit();
            this._trans = undefined;
            return true;
        }
    }
    async rollback() {
        this._transTimes--;
        if (this._trans && this._transTimes == 0) {
            await this._trans.rollback();
            this._trans = undefined;
            return true;
        }
    }
    get checkProxy() {
        return false;
    }
    /**
     * 生成controller对应关系
     * @param ctx 
     */
    controller(ctx: ctx) {
        let path = ctx.path.split('/');
        if (path.length > 1) {
            if (path[0] == "" && path.length > 2) { path.shift() }
            ctx.control = {
                c: path[0],
                m: path.length == 1 ? 'index' : path[1],
            }
        }
    }
    getDbDefine(TableName: string) {
        //加载文件
        try {
            let d = require(path.resolve(path.join(this.AppPath, 'db', TableName)))
            return d.default
        } catch (e) {
            throw new Error(`${ErrorType.DB_DEFINE_NOT_FOUND}_${TableName}`)
        }
    }
    getDbTableFields(TableName: string): string[] {
        return this.getDbDefine(TableName);
    }
    getDbTablePK(TableName: string): string {
        let pk = "";
        forOwn(this.getDbTableFields(TableName), (config: any, field: string) => {
            if (config.primaryKey) pk = field
        })
        return pk;
    }
    getRelation(RelationName: string): Relation | boolean {
        return false;
    }
    get StaticPath(): string {
        return path.join(path.dirname(this.AppPath), 'Public')
    }
    async getStaticFile(p?: string): Promise<void> {
        if (p === undefined) {
            p = path.join(this.StaticPath, this._ctx.path)
        }
        await send(this._ctx, this._ctx.path, {
            root: this.StaticPath,
            index: 'index.html',
            maxage: 86400000,
        })
    }
    get allowCORS(): boolean {
        return true;
    }
    get outformat(): any {
        return {
            d: this._ctx.body !== undefined ? this._ctx.body : '',
            c: this._ctx.error ? 500 : 200,
            i: [this._ctx.control.c, this._ctx.control.m].join('/'),
            e: this._ctx.error ? this._ctx.error : ''
        }
    }
}

export interface CookieOptions {
    domain?: string,
    path?: string,
    maxAge?: number,
    expires?: Date,
    httpOnly?: boolean,
    overwrite?: boolean
}
export interface SessionOptions {
    key: string,
    domain?: string,
    path: string,
    maxAge: number,
    expires?: Date,
    httpOnly?: boolean,
    overwrite?: boolean,
    signed?: boolean
    rolling?: boolean,
    renew?: boolean,
    store?: any,
}